#include "Tree.h"
#include <sys/stat.h>



char* crnt;
enum MError {NOERROR = 0, NONUMBER = 1, NOBKT = 2, NOEOF = 3};
enum MError MERROR;

tree* GetT();
tree* GetN();
tree* GetP();
tree* GetE();
tree* GetG(char* str);
int GetGError();
char* FileToArray(char* FileName);
int NodeDump(tree* this, FILE* here);
int MathDump(tree* this, char* here);

int main()
{
    char FileName[100];
    scanf("%100s", FileName);
    char* expression = FileToArray(FileName);
    if (!expression)
    {
        printf("No such file\n");
        return 0;
    }
    puts(expression);
    tree* exp = GetG(expression);
    free(expression);
    scanf("%100s", FileName);
    MathDump(exp, FileName);
    return 0;
}

tree* GetN()
{
    int val = 0;
    if (! ('0' <= *crnt && *crnt <= '9') )
    {
        MERROR = NONUMBER;
        return NULL;
    }
    else
    {
        while ('0' <= *crnt && *crnt <= '9') val = val*10 + *crnt++ - '0';
    }
    data_t x;
    x.type = 'n';
    x.number = val;
    tree* result = tree_ctor(x);
    return result;
}

tree* GetP()
{
    if (MERROR) return NULL;
    if (*crnt == '(')
    {
        crnt++;
        tree* result = GetE();
        if (MERROR) return NULL;
        if (*crnt == ')')
        {
            crnt++;
            return result;
        }
        else
        {
            MERROR = NOBKT;
            return NULL;
        }
    }
    else return GetN();
}

tree* GetE()
{
    if (MERROR) return NULL;
    tree* result = GetT();
    if (MERROR) return NULL;
    while (*crnt == '+' || *crnt == '-')
    {
        data_t x;
        x.type = 'o';
        if (*crnt == '+') x.op = '+'; else x.op = '-';

        crnt++;
        tree* new_result = tree_ctor(x);
        add_node(new_result, result, 'l');
        tree* NewNumber = GetT();
        if (MERROR) return NULL;
        add_node(new_result, NewNumber, 'r');
        result = new_result;
    }
    return result;
}

tree* GetT()
{
    if (MERROR) return NULL;
    tree* result = GetP();
    if (MERROR) return NULL;
    while (*crnt == '*' || *crnt == '/')
    {
        data_t x;
        x.type = 'o';
        if (*crnt == '*') x.op = '*'; else x.op = '/';

        crnt++;
        tree* new_result = tree_ctor(x);
        add_node(new_result, result, 'l');
        tree* NewNumber = GetP();
        if (MERROR) return NULL;
        add_node(new_result, NewNumber, 'r');
        result = new_result;
    }
    return result;
}

tree* GetG(char* str)
{
    MERROR = NOERROR;
    crnt = str;
    tree* expression = GetE();
    if (MERROR) return NULL;
    if (*crnt == '\0') return expression;
    else
    {
        MERROR = NOEOF;
        return NULL;
    }
}

int GetGError()
{
    return MERROR;
}

char* FileToArray(char* FileName)
{
    assert(FileName);
    FILE* File = fopen(FileName, "r");

    assert(File);

    struct stat buf;

    fstat(fileno(File), &buf);

    long long unsigned Length = (long long unsigned) buf.st_size;

    assert(Length);

    char* result = (char*) calloc(Length + 1, sizeof(*result));
    assert(result);

    for (int i = 0; i < Length - 1; i++)
    {
        fscanf(File, "%c", &result[i]);
    }
    fclose(File);
    File = NULL;
    return result;
}

int MathDump(tree* this, char* here)
{
    FILE* dest = fopen(here, "w");
    if (!dest) return 0;
    if (!tree_ok(this)) return 0;
    int success = NodeDump(this, dest);
    fclose(dest);
    return success;
}

int NodeDump(tree* this, FILE* here)
{
    if (!here) return 0;
    if (!tree_ok(this)) return 0;
    if (this -> data.type == 'o')
    {
        int success1 = NodeDump(this -> left, here);
        int success2 = NodeDump(this -> right, here);
        if (this -> data.op == '+') fprintf(here, "add\n");
        if (this -> data.op == '-') fprintf(here, "sub\n");
        if (this -> data.op == '*') fprintf(here, "mul\n");
        if (this -> data.op == '/') fprintf(here, "div\n");
        return success1 * success2;
    }
    if (this -> data.type == 'n')
    {
        fprintf(here, "push %d\n", this -> data.number);
        return 1;
    }
}

